home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
emulator
/
bsvc-1.000
/
bsvc-1
/
bsvc-1.0.4
/
src
/
UI
/
BtkFileSelector.tk
< prev
next >
Wrap
Text File
|
1995-07-26
|
19KB
|
526 lines
###############################################################################
# $Id: BtkFileSelector.tk,v 1.2 1995/06/30 17:17:57 bmott Exp $
###############################################################################
# BtkFileSelector.tk - File Selector Widget for Tk
#
# Use the procedure BtkFileSelector to open a file selector widget. The
# procedure accepts the following switches:
#
# -in <window> creates the file selector as a child of the window
# -filter <*.setup> Sets the filter to the given string
# -text <message> Message displayed at the top of the file selector
#
# Copyright (c) 1994
# Bradford W. Mott
# September 1,1994
###############################################################################
# $Log: BtkFileSelector.tk,v $
# Revision 1.2 1995/06/30 17:17:57 bmott
# Changed font resources and made the file selector's size depend on
# its parent's size
#
# Revision 1.1 1994/09/13 23:30:03 bmott
# Initial revision
#
#
###############################################################################
set btkFileSelector(path) [pwd]
option add "*btkFileSelector*Font" "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-*" 40
option add "*btkFileSelector*label*Font" "-*-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-*" 40
option add "*btkFileSelector*Foreground" "black" 40
option add "*btkFileSelector*Background" "gray80" 40
option add "*btkFileSelector*activeForeground" "black" 40
option add "*btkFileSelector*activeBackground" "gray65" 40
option add "*btkFileSelector*scrollbar*foreground" "gray80" 40
option add "*btkFileSelector*scrollbar*activeForeground" "gray65" 40
option add "*btkFileSelector*selectForeground" "black" 40
option add "*btkFileSelector*selectBackground" "gray65" 40
###############################################################################
# Fill the selector's listbox with the files in the current directory
###############################################################################
proc BtkFileSelectorUpdate {window} {
global btkFileSelector
## Change the mouse pointer to the watch
$window configure -cursor watch
## Tell tk to update the screen
update idletasks
## Get the filter and path
set filter $btkFileSelector(filter)
set path $btkFileSelector(path)
## Update the filter entry field
$window.filter.entry delete 0 end
$window.filter.entry insert end $filter
BtkFileSelectorEntryAlign $window.filter.entry end
## Update the path entry field
$window.path.entry delete 0 end
$window.path.entry insert end $path
BtkFileSelectorEntryAlign $window.path.entry end
## Get a list of all of the files in the current directory
if {$btkFileSelector(allFiles) == "yes"} {
set files [glob -nocomplain $path/.* $path/*]
set files [lrange $files 2 end]
} else {
set files [glob -nocomplain $path/*]
}
## Start with an empty file list
set filelist ""
## Build the rest of the file list
foreach i $files {
set file [file tail $i]
## Make sure file really exists (This is for wierd file systems like AFS)
if {[file exists "$i"] == 1} {
if {[file isdirectory "$i"] == 1} {
lappend filelist "$file/"
} else {
if {[string match $filter $file] == 1} {
lappend filelist "$file"
}
}
}
}
## Sort the file list
set filelist [lsort $filelist]
## Add the parent directory to the top of the list if we're not at the root
if {$btkFileSelector(path) != ""} {
set filelist [linsert $filelist 0 "../"]
}
## Clear the listbox
$window.selection.listbox delete 0 end
## Put the file list in the listbox
foreach i $filelist {
$window.selection.listbox insert end "$i"
}
## Change the mouse pointer back to the default
$window configure -cursor {}
## Tell tk to update the screen
update idletasks
}
###############################################################################
## Process a click event on a file
###############################################################################
proc BtkFileSelectorFileClicked {window y} {
global btkFileSelector
## Get the listbox item nearest the y coordinate
set nearest [$window nearest $y]
if {$nearest >= 0} {
$window select from $nearest
$window select to $nearest
set file [$window get $nearest]
if {[regexp {^.*/$} $file] == 0} {
## Update the filename entry field
$btkFileSelector(baseWindow).filename.entry delete 0 end
$btkFileSelector(baseWindow).filename.entry insert end $file
}
}
}
###############################################################################
## Process a double click event on a file
###############################################################################
proc BtkFileSelectorFileDoubleClicked {window y} {
global btkFileSelector
## Get the path
set path $btkFileSelector(path)
## Get the listbox item nearest the y coordinate
set nearest [$window nearest $y]
if {$nearest >= 0} {
set file [$window get $nearest]
set filespec $path/$file
## If the file is a directory then try to change directories
if {[regexp {^.*/$} $file] == 1} {
## See if we should move to the parent directory
if {$file == "../"} {
set filespec [file dirname [string trimright $path '/']]/
}
if {([file executable $path/$file]==1)&&([file readable $path/$file]==1)} {
## Update the path
set btkFileSelector(path) [string trimright $filespec '/']
BtkFileSelectorUpdate $btkFileSelector(baseWindow)
} else {
## Get the current color of the background
set current [lindex [$window configure -background] 4]
## Change the background to black
$window configure -background Black
## Tell tk to update the screen
update idletasks
## Wait
after 50
## Restore the background
$window configure -background $current
## Tell tk to update the screen
update idletasks
}
} else {
BtkFileSelectorFileSelected
}
}
}
###############################################################################
## Handle the Okay button
###############################################################################
proc BtkFileSelectorFileSelected {} {
global btkFileSelector
## Get the selected file from the listbox
set file [$btkFileSelector(baseWindow).filename.entry get]
if {$file == ""} { return }
set btkFileSelector(filespec) $btkFileSelector(path)/$file
destroy $btkFileSelector(baseWindow)
}
###############################################################################
## Handle the Cancel button
###############################################################################
proc BtkFileSelectorCanceled {} {
global btkFileSelector
set btkFileSelector(filespec) ""
destroy $btkFileSelector(baseWindow)
}
###############################################################################
## Set the "common" bindings for the entry widgets
###############################################################################
proc BtkFileSelectorSetEntryBindings { window } {
global btkFileSelector
## See if the entry needs to be added to the list of entry widgets
if {[lsearch -exact $btkFileSelector(entryList) $window] == -1} {
lappend btkFileSelector(entryList) $window
}
bind $window <Left> "BtkFileSelectorEntryCursorPositionChange $window -1"
bind $window <Right> "BtkFileSelectorEntryCursorPositionChange $window 1"
bind $window <Tab> "BtkFileSelectorNextEntry"
}
###############################################################################
## Move the focus to the next entry widget
###############################################################################
proc BtkFileSelectorNextEntry {} {
global btkFileSelector
## Get the current focus window path
set current [focus]
set currentIndex [lsearch -exact $btkFileSelector(entryList) $current]
if {$currentIndex == -1} {
set current [lindex $btkFileSelector(entryList) 0]
} else {
set i [expr $currentIndex + 1]
if {$i >= [llength $btkFileSelector(entryList)]} {
set i 0
}
set current [lindex $btkFileSelector(entryList) $i]
}
## Change the entry focus
catch {focus $current}
}
###############################################################################
## Change the position of the insertion cursor in the given entry widget
###############################################################################
proc BtkFileSelectorEntryCursorPositionChange {window offset} {
global btkFileSelector
set pos [$window index insert]
incr pos $offset
if {$pos < 0} {
set pos 0
}
$window icursor $pos
## Move the cursor into view
BtkFileSelectorEntryAlign $window insert
}
###############################################################################
## Tell the entry widget to align the indexed character into view
###############################################################################
proc BtkFileSelectorEntryAlign { window index } {
set c [$window index $index]
set left [$window index @0]
if {$left >= $c} {
if {$c > 0} {
$window view [expr $c-1]
} else {
$window view $c
}
return
}
set x [expr [winfo width $window] - [lindex [$window config -bd] 4] - 1]
while {([$window index @$x] < $c) && ($left < $c)} {
set left [expr $left+1]
$window view $left
}
}
###############################################################################
## Try to change the path to whatever is in the path entry widget
###############################################################################
proc BtkFileSelectorSetPath {} {
global btkFileSelector
## Get the path from the entry widget
set path [string trimright [$btkFileSelector(baseWindow).path.entry get] '/']
## Make sure it's a valid path
if {([file executable $path/]==1)&&([file readable $path/]==1)} {
set btkFileSelector(path) $path
BtkFileSelectorUpdate $btkFileSelector(baseWindow)
} else {
## Update the path entry field
$btkFileSelector(baseWindow).path.entry delete 0 end
$btkFileSelector(baseWindow).path.entry insert end $btkFileSelector(path)
## Right align the view
BtkFileSelectorEntryAlign $btkFileSelector(baseWindow).path.entry insert
}
}
###############################################################################
## Try to change the filter to whatever is in the filter entry widget
###############################################################################
proc BtkFileSelectorSetFilter {} {
global btkFileSelector
## Get the path from the entry widget
set filter [$btkFileSelector(baseWindow).filter.entry get]
## Make sure there is a filter
if {$filter == ""} { set filter "*" }
set btkFileSelector(filter) $filter
BtkFileSelectorUpdate $btkFileSelector(baseWindow)
}
###############################################################################
# Popup a file selector and wait for the user to select something
###############################################################################
proc BtkFileSelector args {
global btkFileSelector
## Clear the entry "next" list
set btkFileSelector(entryList) ""
## Set the return value to nothing
set btkFileSelector(filespec) ""
## Default Message
set btkFileSelector(message) "Files:"
## Default to creating a toplevel window
set btkFileSelector(parentWindow) "root"
## Default Filter
set btkFileSelector(filter) "*"
## Parse the argument list
for {set t 0} {$t < [llength $args]} {incr t} {
set arg [lindex $args $t]
if {$arg == "-text"} {
incr t
set btkFileSelector(message) [lindex $args $t]
} elseif {$arg == "-in"} {
incr t
if {[lindex $args $t] == "."} {
set btkFileSelector(parentWindow) ""
} else {
set btkFileSelector(parentWindow) [lindex $args $t]
}
} elseif {$arg == "-filter"} {
incr t
set btkFileSelector(filter) [lindex $args $t]
} else {
tkerror "Incorrect Arguments to BtkFileSelector!"
return
}
}
## Create a toplevel window or a frame to hold the selector in
if {$btkFileSelector(parentWindow) == "root"} {
set btkFileSelector(baseWindow) ".btkFileSelector"
set btkFileSelector(parentWindow) ".btkFileSelector"
toplevel $btkFileSelector(baseWindow) -borderwidth 4
wm geometry $btkFileSelector(baseWindow) 375x342
wm title $btkFileSelector(baseWindow) "File Selector"
} else {
## Get my parent's width and height
if {$btkFileSelector(parentWindow) == ""} {
scan [winfo geometry .] "%dx%d" parentWidth parentHeight
} else {
scan [winfo geometry $btkFileSelector(parentWindow)] "%dx%d" parentWidth parentHeight
}
## Calculate size of my frame based on my parent's size
if {$parentWidth > 375} {
set myWidth 375
} else {
set myWidth [expr $parentWidth - 20]
}
if {$parentHeight > 350} {
set myHeight 350
} else {
set myHeight [expr $parentHeight - 20]
}
## Create my frame
set btkFileSelector(baseWindow) \
"$btkFileSelector(parentWindow).btkFileSelector"
frame $btkFileSelector(baseWindow) -borderwidth 5 -relief ridge \
-height $myHeight -width $myWidth
place $btkFileSelector(baseWindow) -relx 0.5 -rely 0.5 -anchor center
## Turn off geometry propagation for the packer
pack propagate $btkFileSelector(baseWindow) 0
}
frame $btkFileSelector(baseWindow).path
label $btkFileSelector(baseWindow).path.label -text "Path:" -anchor w
entry $btkFileSelector(baseWindow).path.entry -relief sunken
BtkFileSelectorSetEntryBindings $btkFileSelector(baseWindow).path.entry
bind $btkFileSelector(baseWindow).path.entry \
<Return> "BtkFileSelectorSetPath"
pack $btkFileSelector(baseWindow).path.label -side left
pack $btkFileSelector(baseWindow).path.entry -side left -fill x -expand 1
frame $btkFileSelector(baseWindow).filename
label $btkFileSelector(baseWindow).filename.label \
-text "File name:" -anchor w
entry $btkFileSelector(baseWindow).filename.entry -relief sunken
BtkFileSelectorSetEntryBindings $btkFileSelector(baseWindow).filename.entry
bind $btkFileSelector(baseWindow).filename.entry \
<Return> "BtkFileSelectorFileSelected"
pack $btkFileSelector(baseWindow).filename.label -side left
pack $btkFileSelector(baseWindow).filename.entry -side left \
-fill x -expand 1
frame $btkFileSelector(baseWindow).filter
label $btkFileSelector(baseWindow).filter.label -text "Filter:" -anchor w
entry $btkFileSelector(baseWindow).filter.entry -relief sunken -width 10
BtkFileSelectorSetEntryBindings $btkFileSelector(baseWindow).filter.entry
bind $btkFileSelector(baseWindow).filter.entry \
<Return> "BtkFileSelectorSetFilter"
checkbutton $btkFileSelector(baseWindow).filter.all \
-text "Show all files" -offvalue "no" -onvalue "yes" \
-variable btkFileSelector(allFiles) \
-command {BtkFileSelectorUpdate $btkFileSelector(baseWindow)}
pack $btkFileSelector(baseWindow).filter.label -side left
pack $btkFileSelector(baseWindow).filter.entry -side left -fill x \
-expand 1 -padx 4
pack $btkFileSelector(baseWindow).filter.all -side left
frame $btkFileSelector(baseWindow).selection
label $btkFileSelector(baseWindow).selection.label \
-text $btkFileSelector(message)
scrollbar $btkFileSelector(baseWindow).selection.scrollbar \
-relief sunken -orient vertical \
-command "$btkFileSelector(baseWindow).selection.listbox yview"
listbox $btkFileSelector(baseWindow).selection.listbox \
-relief sunken -geometry 20x4 \
-yscroll "$btkFileSelector(baseWindow).selection.scrollbar set"
tk_listboxSingleSelect $btkFileSelector(baseWindow).selection.listbox
bind $btkFileSelector(baseWindow).selection.listbox <Double-ButtonRelease-1> \
"BtkFileSelectorFileDoubleClicked %W %y"
bind $btkFileSelector(baseWindow).selection.listbox <ButtonPress-1> \
"BtkFileSelectorFileClicked %W %y"
bind $btkFileSelector(baseWindow).selection.listbox <Button1-Motion> \
"BtkFileSelectorFileClicked %W %y"
pack $btkFileSelector(baseWindow).selection.label \
-side top -anchor w -fill x
pack $btkFileSelector(baseWindow).selection.scrollbar \
-side left -fill y
pack $btkFileSelector(baseWindow).selection.listbox \
-side left -fill both -expand 1
frame $btkFileSelector(baseWindow).button
button $btkFileSelector(baseWindow).button.okay \
-text "Okay" -command "BtkFileSelectorFileSelected"
button $btkFileSelector(baseWindow).button.filter \
-text "Filter" -command "BtkFileSelectorSetFilter"
button $btkFileSelector(baseWindow).button.cancel \
-text "Cancel" -command "BtkFileSelectorCanceled"
pack $btkFileSelector(baseWindow).button.okay \
-side left -fill x -expand 1
pack $btkFileSelector(baseWindow).button.filter \
-side left -fill x -expand 1 -padx 4
pack $btkFileSelector(baseWindow).button.cancel \
-side left -fill x -expand 1
pack $btkFileSelector(baseWindow).selection \
-side top -padx 4 -pady 2 -fill both -expand 1
pack $btkFileSelector(baseWindow).path \
-side top -padx 4 -fill x
pack $btkFileSelector(baseWindow).filename \
-side top -padx 4 -fill x
pack $btkFileSelector(baseWindow).filter \
-side top -padx 4 -fill x
pack $btkFileSelector(baseWindow).button \
-side top -padx 4 -pady 7 -fill x
## Update the file selector's file list
BtkFileSelectorUpdate $btkFileSelector(baseWindow)
## Make this a modal dialog
tkwait visibility $btkFileSelector(baseWindow)
while {[catch {grab set $btkFileSelector(baseWindow)}] == 1} {}
tkwait window $btkFileSelector(baseWindow)
## Tell tk to update the screen (i.e. remove the file selector window)
update idletasks
return $btkFileSelector(filespec)
}